home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / frasrc19.zip / LSYS.C < prev    next >
C/C++ Source or Header  |  1995-02-25  |  26KB  |  966 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #ifdef __TURBOC__
  6. #include <alloc.h>
  7. #else
  8. #include <malloc.h>
  9. #endif
  10. #include "fractint.h"
  11. #include "prototyp.h"
  12. #include "lsys.h"
  13.  
  14. struct lsys_cmd {
  15.     void (*f)(struct lsys_turtlestatei *);
  16.     long n;
  17.     char ch;
  18. };
  19.  
  20. static int _fastcall readLSystemFile(char *);
  21. static void _fastcall free_rules_mem(void);
  22. static int _fastcall save_rule(char *,char far **);
  23. static void free_lcmds(void);
  24. static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_turtlestatei *, struct lsys_cmd far **,int);
  25. static struct lsys_cmd far * drawLSysI(struct lsys_cmd far *command,struct lsys_turtlestatei *ts, struct lsys_cmd far **rules,int depth);
  26. static int lsysi_findscale(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth);
  27. static struct lsys_cmd far *LSysISizeTransform(char far *s, struct lsys_turtlestatei *ts);
  28. static struct lsys_cmd far *LSysIDrawTransform(char far *s, struct lsys_turtlestatei *ts);
  29. static void _fastcall lsysi_dosincos(void);
  30.  
  31. static void lsysi_doslash(struct lsys_turtlestatei *cmd);
  32. static void lsysi_dobslash(struct lsys_turtlestatei *cmd);
  33. static void lsysi_doat(struct lsys_turtlestatei *cmd);
  34. static void lsysi_dopipe(struct lsys_turtlestatei *cmd);
  35. static void lsysi_dosizedm(struct lsys_turtlestatei *cmd);
  36. static void lsysi_dosizegf(struct lsys_turtlestatei *cmd);
  37. static void lsysi_dodrawd(struct lsys_turtlestatei *cmd);
  38. static void lsysi_dodrawm(struct lsys_turtlestatei *cmd);
  39. static void lsysi_dodrawg(struct lsys_turtlestatei *cmd);
  40. static void lsysi_dodrawf(struct lsys_turtlestatei *cmd);
  41. static void lsysi_dodrawc(struct lsys_turtlestatei *cmd);
  42. static void lsysi_dodrawgt(struct lsys_turtlestatei *cmd);
  43. static void lsysi_dodrawlt(struct lsys_turtlestatei *cmd);
  44.  
  45. /* Some notes to Adrian from PB, made when I integrated with v15:
  46.      printfs changed to work with new user interface
  47.      bug at end of readLSystemFile, the line which said rulind=0 fixed
  48.        to say *rulind=0
  49.      the calloc was not worthwhile, it was just for a 54 byte area, cheaper
  50.        to keep it as a static;    but there was a static 201 char buffer I
  51.        changed to not be static
  52.      use of strdup was a nono, caused problems running out of space cause
  53.        the memory allocated each time was never freed; I've changed to
  54.        use far memory and to free when done
  55.    */
  56.  
  57. #define sins ((long *)(boxy))
  58. #define coss (((long *)(boxy)+50)) /* 50 after the start of sins */
  59. static char far *ruleptrs[MAXRULES];
  60. static struct lsys_cmd far *rules2[MAXRULES];
  61. char maxangle;
  62. static char loaded=0;
  63.  
  64.  
  65. int _fastcall ispow2(int n)
  66. {
  67.   return (n == (n & -n));
  68. }
  69.  
  70. LDBL _fastcall getnumber(char far **str)
  71. {
  72.    char numstr[30];
  73.    LDBL ret;
  74.    int i,root,inverse;
  75.  
  76.    root=0;
  77.    inverse=0;
  78.    strcpy(numstr,"");
  79.    (*str)++;
  80.    switch (**str)
  81.    {
  82.    case 'q':
  83.       root=1;
  84.       (*str)++;
  85.       break;
  86.    case 'i':
  87.       inverse=1;
  88.       (*str)++;
  89.       break;
  90.    }
  91.    switch (**str)
  92.    {
  93.    case 'q':
  94.       root=1;
  95.       (*str)++;
  96.       break;
  97.    case 'i':
  98.       inverse=1;
  99.       (*str)++;
  100.       break;
  101.    }
  102.    i=0;
  103.    while ((**str<='9' && **str>='0') || **str=='.')
  104.    {
  105.       numstr[i++]= **str;
  106.       (*str)++;
  107.    }
  108.    (*str)--;
  109.    numstr[i]=0;
  110.    ret=atof(numstr);
  111.    if (ret <= 0.0) /* this is a sanity check, JCO 8/31/94 */
  112.       return 0;
  113.    if (root)
  114.      ret=sqrtl(ret);
  115.    if (inverse)
  116.      ret = 1.0/ret;
  117.    return ret;
  118. }
  119.  
  120. static int _fastcall readLSystemFile(char *str)
  121. {
  122.    int c;
  123.    char far **rulind;
  124.    int err=0;
  125.    int linenum,check=0;
  126.    char inline[161],fixed[161],*word;
  127.    FILE *infile;
  128.    char msgbuf[481]; /* enough for 6 full lines */
  129.  
  130.    if (find_file_item(LFileName,str,&infile) < 0)
  131.       return -1;
  132.    while ((c = fgetc(infile)) != '{')
  133.       if (c == EOF) return -1;
  134.  
  135.    maxangle=0;
  136.    for(linenum=0;linenum<MAXRULES;++linenum) ruleptrs[linenum]=NULL;
  137.    rulind= &ruleptrs[1];
  138.    msgbuf[0]=(char)(linenum=0);
  139.  
  140.    while(file_gets(inline,160,infile))  /* Max line length 160 chars */
  141.    {
  142.       linenum++;
  143.       if ((word = strchr(inline,';')) != NULL) /* strip comment */
  144.      *word = 0;
  145.       strlwr(inline);
  146.  
  147.       if (strspn(inline," \t\n") < strlen(inline)) /* not a blank line */
  148.       {
  149.      word=strtok(inline," =\t\n");
  150.      if (!strcmp(word,"axiom"))
  151.      {
  152.         if (save_rule(strtok(NULL," \t\n"),&ruleptrs[0])) {
  153.             strcat(msgbuf,"Error:  out of memory\n");
  154.             ++err;
  155.         break;
  156.             }
  157.         check=1;
  158.      }
  159.      else if (!strcmp(word,"angle"))
  160.      {
  161.         maxangle=(char)atoi(strtok(NULL," \t\n"));
  162.         check=1;
  163.      }
  164.      else if (!strcmp(word,"}"))
  165.         break;
  166.      else if (strcspn(word,"+-/\\@|!c<>][") == 0 && strlen(word) == 1)
  167.         {
  168.            sprintf(&msgbuf[strlen(msgbuf)],
  169.            "Syntax error line %d: Redefined reserved symbol %s\n",linenum,word);
  170.            ++err;
  171.            break;
  172.         }
  173.      else if (strlen(word)==1)
  174.      {
  175.         strcat(strcpy(fixed,word),strtok(NULL," \t\n"));
  176.         if (save_rule(fixed,rulind++)) {
  177.         strcat(msgbuf, "Error:  out of memory\n");
  178.         ++err;
  179.                 break;
  180.             }
  181.         check=1;
  182.      }
  183.      else
  184.         if (err<6)
  185.         {
  186.            sprintf(&msgbuf[strlen(msgbuf)],
  187.                "Syntax error line %d: %s\n",linenum,word);
  188.            ++err;
  189.         }
  190.      if (check)
  191.      {
  192.         check=0;
  193.         if((word=strtok(NULL," \t\n"))!=NULL)
  194.            if (err<6)
  195.            {
  196.           sprintf(&msgbuf[strlen(msgbuf)],
  197.              "Extra text after command line %d: %s\n",linenum,word);
  198.           ++err;
  199.            }
  200.      }
  201.       }
  202.    }
  203.    fclose(infile);
  204.    if (!ruleptrs[0] && err<6)
  205.    {
  206.       strcat(msgbuf,"Error:  no axiom\n");
  207.       ++err;
  208.    }
  209.    if ((maxangle<3||maxangle>50) && err<6)
  210.    {
  211.       strcat(msgbuf,"Error:  illegal or missing angle\n");
  212.       ++err;
  213.    }
  214.    if (err)
  215.    {
  216.       msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */
  217.       stopmsg(0,msgbuf);
  218.       return -1;
  219.    }
  220.    *rulind=NULL;
  221.    return 0;
  222. }
  223.  
  224. int Lsystem(void)
  225. {
  226.    int order;
  227.    char far **rulesc;
  228.    struct lsys_cmd far **sc;
  229.    int stackoflow = 0;
  230.  
  231.    if ( (!loaded) && LLoad())
  232.      return -1;
  233.  
  234.    overflow = 0;        /* reset integer math overflow flag */
  235.  
  236.    order=(int)param[0];
  237.    if (order<=0)
  238.      order=0;
  239.    if (usr_floatflag)
  240.     overflow = 1;
  241.    else {
  242.     struct lsys_turtlestatei ts;
  243.  
  244.     ts.stackoflow = 0;
  245.     ts.maxangle = maxangle;
  246.         ts.dmaxangle = (char)(maxangle - 1);
  247.  
  248.     sc = rules2;
  249.     for (rulesc = ruleptrs; *rulesc; rulesc++)
  250.         *sc++ = LSysISizeTransform(*rulesc, &ts);
  251.     *sc = NULL;
  252.  
  253.     lsysi_dosincos();
  254.     if (lsysi_findscale(rules2[0], &ts, &rules2[1], order)) {
  255.         ts.realangle = ts.angle = ts.reverse = 0;
  256.  
  257.         free_lcmds();
  258.         sc = rules2;
  259.         for (rulesc = ruleptrs; *rulesc; rulesc++)
  260.         *sc++ = LSysIDrawTransform(*rulesc, &ts);
  261.         *sc = NULL;
  262.  
  263.         /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
  264.         if ((ts.curcolor=15) > colors)
  265.             ts.curcolor=(char)(colors-1);
  266.         drawLSysI(rules2[0], &ts, &rules2[1], order);
  267.     }
  268.     stackoflow = ts.stackoflow;
  269.    }
  270.  
  271.    if (stackoflow) {
  272.       static char far msg[]={"insufficient memory, try a lower order"};
  273.       stopmsg(0,msg);
  274.    }
  275.    else if (overflow) {
  276.     struct lsys_turtlestatef ts;
  277.  
  278.     overflow = 0;
  279.  
  280.     ts.stackoflow = 0;
  281.     ts.maxangle = maxangle;
  282.         ts.dmaxangle = (char)(maxangle - 1);
  283.  
  284.     sc = rules2;
  285.     for (rulesc = ruleptrs; *rulesc; rulesc++)
  286.         *sc++ = LSysFSizeTransform(*rulesc, &ts);
  287.     *sc = NULL;
  288.  
  289.     lsysf_dosincos();
  290.     if (lsysf_findscale(rules2[0], &ts, &rules2[1], order)) {
  291.         ts.realangle = ts.angle = ts.reverse = 0;
  292.  
  293.         free_lcmds();
  294.         sc = rules2;
  295.         for (rulesc = ruleptrs; *rulesc; rulesc++)
  296.         *sc++ = LSysFDrawTransform(*rulesc, &ts);
  297.         *sc = NULL;
  298.  
  299.         /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
  300.         if ((ts.curcolor=15) > colors)
  301.             ts.curcolor=(char)(colors-1);
  302.         lsys_prepfpu(&ts);
  303.         drawLSysF(rules2[0], &ts, &rules2[1], order);
  304.         lsys_donefpu(&ts);
  305.     }
  306.         overflow = 0;
  307.    }
  308.    free_rules_mem();
  309.    free_lcmds();
  310.    loaded=0;
  311.    return 0;
  312. }
  313.  
  314. int LLoad(void)
  315. {
  316.    if (readLSystemFile(LName)) { /* error occurred */
  317.       free_rules_mem();
  318.       loaded=0;
  319.       return -1;
  320.    }
  321.    loaded=1;
  322.    return 0;
  323. }
  324.  
  325. static void _fastcall free_rules_mem(void)
  326. {
  327.    int i;
  328.    for(i=0;i<MAXRULES;++i)
  329.       if(ruleptrs[i]) farmemfree(ruleptrs[i]);
  330. }
  331.  
  332. static int _fastcall save_rule(char *rule,char far **saveptr)
  333. {
  334.    int i;
  335.    char far *tmpfar;
  336.    i=strlen(rule)+1;
  337.    if((tmpfar=farmemalloc((long)i))==NULL) {
  338.        return -1;
  339.    }
  340.    *saveptr=tmpfar;
  341.    while(--i>=0) *(tmpfar++)= *(rule++);
  342.    return 0;
  343. }
  344.  
  345. static void free_lcmds(void)
  346. {
  347.   struct lsys_cmd far **sc = rules2;
  348.  
  349.   while (*sc)
  350.     farmemfree(*sc++);
  351. }
  352.  
  353.  
  354.  
  355. #ifdef XFRACT
  356. #define lsysi_doslash_386 lsysi_doslash
  357. #define lsysi_dobslash_386 lsysi_dobslash
  358. #define lsys_doat lsysi_doat
  359. #define lsys_dosizegf lsysi_dosizegf
  360. #define lsys_dodrawg lsysi_dodrawg
  361. void lsys_prepfpu(struct lsys_turtlestatef *x) { }
  362. void lsys_donefpu(struct lsys_turtlestatef *x) { }
  363. #endif
  364.  
  365. /* integer specific routines */
  366.  
  367. #ifdef XFRACT
  368. static void lsysi_doplus(struct lsys_turtlestatei *cmd)
  369. {
  370.     if (cmd->reverse) {
  371.     if (++cmd->angle == cmd->maxangle)
  372.         cmd->angle = 0;
  373.     }
  374.     else {
  375.     if (cmd->angle)
  376.         cmd->angle--;
  377.     else
  378.         cmd->angle = cmd->dmaxangle;
  379.     }
  380. }
  381. #else
  382. extern void lsysi_doplus(struct lsys_turtlestatei *cmd);
  383. #endif
  384.  
  385. #ifdef XFRACT
  386. /* This is the same as lsys_doplus, except maxangle is a power of 2. */
  387. static void lsysi_doplus_pow2(struct lsys_turtlestatei *cmd)
  388. {
  389.     if (cmd->reverse) {
  390.     cmd->angle++;
  391.     cmd->angle &= cmd->dmaxangle;
  392.     }
  393.     else {
  394.     cmd->angle--;
  395.     cmd->angle &= cmd->dmaxangle;
  396.     }
  397. }
  398. #else
  399. extern void lsysi_doplus_pow2(struct lsys_turtlestatei *cmd);
  400. #endif
  401.  
  402. #ifdef XFRACT
  403. static void lsysi_dominus(struct lsys_turtlestatei *cmd)
  404. {
  405.     if (cmd->reverse) {
  406.     if (cmd->angle)
  407.         cmd->angle--;
  408.     else
  409.         cmd->angle = cmd->dmaxangle;
  410.     }
  411.     else {
  412.     if (++cmd->angle == cmd->maxangle)
  413.         cmd->angle = 0;
  414.     }
  415. }
  416. #else
  417. extern void lsysi_dominus(struct lsys_turtlestatei *cmd);
  418. #endif
  419.  
  420. #ifdef XFRACT
  421. static void lsysi_dominus_pow2(struct lsys_turtlestatei *cmd)
  422. {
  423.     if (cmd->reverse) {
  424.     cmd->angle--;
  425.     cmd->angle &= cmd->dmaxangle;
  426.     }
  427.     else {
  428.     cmd->angle++;
  429.     cmd->angle &= cmd->dmaxangle;
  430.     }
  431. }
  432. #else
  433. extern void lsysi_dominus_pow2(struct lsys_turtlestatei *cmd);
  434. #endif
  435.  
  436. static void lsysi_doslash(struct lsys_turtlestatei *cmd)
  437. {
  438.     if (cmd->reverse)
  439.     cmd->realangle -= cmd->num;
  440.     else
  441.     cmd->realangle += cmd->num;
  442. }
  443.  
  444. #ifndef XFRACT
  445. extern void lsysi_doslash_386(struct lsys_turtlestatei *cmd);
  446. #endif
  447.  
  448. static void lsysi_dobslash(struct lsys_turtlestatei *cmd)
  449. {
  450.     if (cmd->reverse)
  451.     cmd->realangle += cmd->num;
  452.     else
  453.     cmd->realangle -= cmd->num;
  454. }
  455.  
  456. #ifndef XFRACT
  457. extern void lsysi_dobslash_386(struct lsys_turtlestatei *cmd);
  458. #endif
  459.  
  460. static void lsysi_doat(struct lsys_turtlestatei *cmd)
  461. {
  462.     cmd->size = multiply(cmd->size, cmd->num, 19);
  463. }
  464.  
  465. static void lsysi_dopipe(struct lsys_turtlestatei *cmd)
  466. {
  467.     cmd->angle = (char)(cmd->angle + (char)(cmd->maxangle / 2));
  468.     cmd->angle %= cmd->maxangle;
  469. }
  470.  
  471. #ifdef XFRACT
  472. static void lsysi_dopipe_pow2(struct lsys_turtlestatei *cmd)
  473. {
  474.     cmd->angle += cmd->maxangle >> 1;
  475.     cmd->angle &= cmd->dmaxangle;
  476. }
  477. #else
  478. extern void lsysi_dopipe_pow2(struct lsys_turtlestatei *cmd);
  479. #endif
  480.  
  481. #ifdef XFRACT
  482. static void lsysi_dobang(struct lsys_turtlestatei *cmd)
  483. {
  484.     cmd->reverse = ! cmd->reverse;
  485. }
  486. #else
  487. extern void lsysi_dobang(struct lsys_turtlestatei *cmd);
  488. #endif
  489.  
  490. static void lsysi_dosizedm(struct lsys_turtlestatei *cmd)
  491. {
  492.     double angle = (double) cmd->realangle * ANGLE2DOUBLE;
  493.     double s, c;
  494.     long fixedsin, fixedcos;
  495.  
  496.     FPUsincos(&angle, &s, &c);
  497.     fixedsin = (long) (s * FIXEDLT1);
  498.     fixedcos = (long) (c * FIXEDLT1);
  499.  
  500.     cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
  501.     cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
  502.  
  503. /* xpos+=size*aspect*cos(realangle*PI/180); */
  504. /* ypos+=size*sin(realangle*PI/180); */
  505.     if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
  506.     if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
  507.     if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
  508.     if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
  509. }
  510.  
  511. static void lsysi_dosizegf(struct lsys_turtlestatei *cmd)
  512. {
  513.   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[cmd->angle], 29));
  514.   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[cmd->angle], 29));
  515. /* xpos+=size*coss[angle]; */
  516. /* ypos+=size*sins[angle]; */
  517.   if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
  518.   if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
  519.   if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
  520.   if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
  521. }
  522.  
  523. static void lsysi_dodrawd(struct lsys_turtlestatei *cmd)
  524. {
  525.   double angle = (double) cmd->realangle * ANGLE2DOUBLE;
  526.   double s, c;
  527.   long fixedsin, fixedcos;
  528.   int lastx, lasty;
  529.  
  530.   FPUsincos(&angle, &s, &c);
  531.   fixedsin = (long) (s * FIXEDLT1);
  532.   fixedcos = (long) (c * FIXEDLT1);
  533.  
  534.   lastx=(int) (cmd->xpos >> 19);
  535.   lasty=(int) (cmd->ypos >> 19);
  536.   cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
  537.   cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
  538. /* xpos+=size*aspect*cos(realangle*PI/180); */
  539. /* ypos+=size*sin(realangle*PI/180); */
  540.   draw_line(lastx,lasty,(int)(cmd->xpos >> 19),(int)(cmd->ypos >> 19),cmd->curcolor);
  541. }
  542.  
  543. static void lsysi_dodrawm(struct lsys_turtlestatei *cmd)
  544. {
  545.   double angle = (double) cmd->realangle * ANGLE2DOUBLE;
  546.   double s, c;
  547.   long fixedsin, fixedcos;
  548.  
  549.   FPUsincos(&angle, &s, &c);
  550.   fixedsin = (long) (s * FIXEDLT1);
  551.   fixedcos = (long) (c * FIXEDLT1);
  552.  
  553. /* xpos+=size*aspect*cos(realangle*PI/180); */
  554. /* ypos+=size*sin(realangle*PI/180); */
  555.   cmd->xpos = cmd->xpos + (multiply(multiply(cmd->size, cmd->aspect, 19), fixedcos, 29));
  556.   cmd->ypos = cmd->ypos + (multiply(cmd->size, fixedsin, 29));
  557. }
  558.  
  559. static void lsysi_dodrawg(struct lsys_turtlestatei *cmd)
  560. {
  561.   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[cmd->angle], 29));
  562.   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[cmd->angle], 29));
  563. /* xpos+=size*coss[angle]; */
  564. /* ypos+=size*sins[angle]; */
  565. }
  566.  
  567. static void lsysi_dodrawf(struct lsys_turtlestatei *cmd)
  568. {
  569.   int lastx = (int) (cmd->xpos >> 19);
  570.   int lasty = (int) (cmd->ypos >> 19);
  571.   cmd->xpos = cmd->xpos + (multiply(cmd->size, coss[cmd->angle], 29));
  572.   cmd->ypos = cmd->ypos + (multiply(cmd->size, sins[cmd->angle], 29));
  573. /* xpos+=size*coss[angle]; */
  574. /* ypos+=size*sins[angle]; */
  575.   draw_line(lastx,lasty,(int)(cmd->xpos >> 19),(int)(cmd->ypos >> 19),cmd->curcolor);
  576. }
  577.  
  578. static void lsysi_dodrawc(struct lsys_turtlestatei *cmd)
  579. {
  580.   cmd->curcolor = (char)(((int) cmd->num) % colors);
  581. }
  582.  
  583. static void lsysi_dodrawgt(struct lsys_turtlestatei *cmd)
  584. {
  585.   cmd->curcolor = (char)(cmd->curcolor - (char)cmd->num);
  586.   if ((cmd->curcolor %= colors) == 0)
  587.     cmd->curcolor = (char)(colors-1);
  588. }
  589.  
  590. static void lsysi_dodrawlt(struct lsys_turtlestatei *cmd)
  591. {
  592.   cmd->curcolor = (char)(cmd->curcolor + (char)cmd->num);
  593.   if ((cmd->curcolor %= colors) == 0)
  594.     cmd->curcolor = 1;
  595. }
  596.  
  597. static struct lsys_cmd far * _fastcall
  598. findsize(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth)
  599. {
  600.    struct lsys_cmd far **rulind;
  601.    int tran;
  602.  
  603. if (overflow)     /* integer math routines overflowed */
  604.     return NULL;
  605.  
  606. #ifndef __TURBOC__
  607.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  608.       ts->stackoflow = 1;
  609.       return NULL;
  610.       }
  611. #endif
  612.  
  613.    while (command->ch && command->ch !=']') {
  614.       if (! (ts->counter++)) {
  615.      /* let user know we're not dead */
  616.      if (thinking(1,"L-System thinking (higher orders take longer)")) {
  617.         ts->counter--;
  618.         return NULL;
  619.      }
  620.       }
  621.       tran=0;
  622.       if (depth) {
  623.      for(rulind=rules;*rulind;rulind++)
  624.         if ((*rulind)->ch==command->ch) {
  625.            tran=1;
  626.            if (findsize((*rulind)+1,ts,rules,depth-1) == NULL)
  627.           return(NULL);
  628.         }
  629.       }
  630.       if (!depth || !tran) {
  631.     if (command->f) {
  632.       ts->num = command->n;
  633.       (*command->f)(ts);
  634.       }
  635.     else if (command->ch == '[') {
  636.       char saveang,saverev;
  637.       long savesize,savex,savey;
  638.       unsigned long saverang;
  639.  
  640.       saveang=ts->angle;
  641.       saverev=ts->reverse;
  642.       savesize=ts->size;
  643.       saverang=ts->realangle;
  644.       savex=ts->xpos;
  645.       savey=ts->ypos;
  646.       if ((command=findsize(command+1,ts,rules,depth)) == NULL)
  647.          return(NULL);
  648.       ts->angle=saveang;
  649.       ts->reverse=saverev;
  650.       ts->size=savesize;
  651.       ts->realangle=saverang;
  652.       ts->xpos=savex;
  653.       ts->ypos=savey;
  654.     }
  655.       }
  656.       command++;
  657.    }
  658.    return command;
  659. }
  660.  
  661. static int
  662. lsysi_findscale(struct lsys_cmd far *command, struct lsys_turtlestatei *ts, struct lsys_cmd far **rules, int depth)
  663. {
  664.    float horiz,vert;
  665.    double xmin, xmax, ymin, ymax;
  666.    double locsize;
  667.    double locaspect;
  668.    struct lsys_cmd far *fsret;
  669.  
  670.    locaspect=screenaspect*xdots/ydots;
  671.    ts->aspect = FIXEDPT(locaspect);
  672.    ts->xpos =
  673.    ts->ypos =
  674.    ts->xmin =
  675.    ts->xmax =
  676.    ts->ymax =
  677.    ts->ymin =
  678.    ts->realangle =
  679.    ts->angle =
  680.    ts->reverse =
  681.    ts->counter = 0;
  682.    ts->size=FIXEDPT(1L);
  683.    fsret = findsize(command,ts,rules,depth);
  684.    thinking(0, NULL); /* erase thinking message if any */
  685.    xmin = (double) ts->xmin / FIXEDMUL;
  686.    xmax = (double) ts->xmax / FIXEDMUL;
  687.    ymin = (double) ts->ymin / FIXEDMUL;
  688.    ymax = (double) ts->ymax / FIXEDMUL;
  689.    if (fsret == NULL)
  690.       return 0;
  691.    if (xmax == xmin)
  692.       horiz = (float)1E37;
  693.    else
  694.       horiz = (float)((xdots-10)/(xmax-xmin));
  695.    if (ymax == ymin)
  696.       vert = (float)1E37;
  697.    else
  698.       vert = (float)((ydots-6) /(ymax-ymin));
  699.    locsize = (vert<horiz) ? vert : horiz;
  700.  
  701.    if (horiz == 1E37)
  702.       ts->xpos = FIXEDPT(xdots/2);
  703.    else
  704. /*    ts->xpos = FIXEDPT(-xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2); */
  705.       ts->xpos = FIXEDPT((xdots-locsize*(xmax+xmin))/2);
  706.    if (vert == 1E37)
  707.       ts->ypos = FIXEDPT(ydots/2);
  708.    else
  709. /*    ts->ypos = FIXEDPT(-ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2); */
  710.       ts->ypos = FIXEDPT((ydots-locsize*(ymax+ymin))/2);
  711.    ts->size = FIXEDPT(locsize);
  712.  
  713.    return 1;
  714. }
  715.  
  716. static struct lsys_cmd far * 
  717. drawLSysI(struct lsys_cmd far *command,struct lsys_turtlestatei *ts, struct lsys_cmd far **rules,int depth)
  718. {
  719.    struct lsys_cmd far **rulind;
  720.    int tran;
  721.  
  722. if (overflow)     /* integer math routines overflowed */
  723.     return NULL;
  724.  
  725. #ifndef __TURBOC__
  726.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  727.       ts->stackoflow = 1;
  728.       return NULL;
  729.       }
  730. #endif
  731.  
  732.    while (command->ch && command->ch !=']') {
  733.       if (!(ts->counter++)) {
  734.      if (keypressed()) {
  735.         ts->counter--;
  736.         return NULL;
  737.      }
  738.       }
  739.       tran=0;
  740.       if (depth) {
  741.      for(rulind=rules;*rulind;rulind++)
  742.         if ((*rulind)->ch == command->ch) {
  743.            tran=1;
  744.            if (drawLSysI((*rulind)+1,ts,rules,depth-1) == NULL)
  745.           return NULL;
  746.         }
  747.       }
  748.       if (!depth||!tran) {
  749.     if (command->f) {
  750.       ts->num = command->n;
  751.       (*command->f)(ts);
  752.       }
  753.     else if (command->ch == '[') {
  754.       char saveang,saverev,savecolor;
  755.       long savesize,savex,savey;
  756.       unsigned long saverang;
  757.  
  758.       saveang=ts->angle;
  759.       saverev=ts->reverse;
  760.       savesize=ts->size;
  761.       saverang=ts->realangle;
  762.       savex=ts->xpos;
  763.       savey=ts->ypos;
  764.       savecolor=ts->curcolor;
  765.       if ((command=drawLSysI(command+1,ts,rules,depth)) == NULL)
  766.          return(NULL);
  767.       ts->angle=saveang;
  768.       ts->reverse=saverev;
  769.       ts->size=savesize;
  770.       ts->realangle=saverang;
  771.       ts->xpos=savex;
  772.       ts->ypos=savey;
  773.       ts->curcolor=savecolor;
  774.     }
  775.       }
  776.       command++;
  777.    }
  778.    return command;
  779. }
  780.  
  781. static struct lsys_cmd far *
  782. LSysISizeTransform(char far *s, struct lsys_turtlestatei *ts)
  783. {
  784.   struct lsys_cmd far *ret;
  785.   struct lsys_cmd far *doub;
  786.   int maxval = 10;
  787.   int n = 0;
  788.   void (*f)();
  789.   long num;
  790.  
  791.   void (*plus)() = (ispow2(ts->maxangle)) ? lsysi_doplus_pow2 : lsysi_doplus;
  792.   void (*minus)() = (ispow2(ts->maxangle)) ? lsysi_dominus_pow2 : lsysi_dominus;
  793.   void (*pipe)() = (ispow2(ts->maxangle)) ? lsysi_dopipe_pow2 : lsysi_dopipe;
  794.  
  795.   void (*slash)() =  (cpu >= 386) ? lsysi_doslash_386 : lsysi_doslash;
  796.   void (*bslash)() = (cpu >= 386) ? lsysi_dobslash_386 : lsysi_dobslash;
  797.   void (*at)() =     (cpu >= 386) ? lsysi_doat_386 : lsysi_doat;
  798.   void (*dogf)() =   (cpu >= 386) ? lsysi_dosizegf_386 : lsysi_dosizegf;
  799.  
  800.   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
  801.   if (ret == NULL) {
  802.        ts->stackoflow = 1;
  803.        return NULL;
  804.        }
  805.   while (*s) {
  806.     f = NULL;
  807.     num = 0;
  808.     ret[n].ch = *s;
  809.     switch (*s) {
  810.       case '+': f = plus;            break;
  811.       case '-': f = minus;           break;
  812.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  813.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  814.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  815.       case '|': f = pipe;            break;
  816.       case '!': f = lsysi_dobang;     break;
  817.       case 'd':
  818.       case 'm': f = lsysi_dosizedm;   break;
  819.       case 'g':
  820.       case 'f': f = dogf;       break;
  821.       case '[': num = 1;        break;
  822.       case ']': num = 2;        break;
  823.       default:
  824.     num = 3;
  825.     break;
  826.     }
  827. #ifdef XFRACT
  828.     ret[n].f = (void (*)())f;
  829. #else
  830.     ret[n].f = (void (*)(struct lsys_turtlestatei *))f;
  831. #endif
  832.     ret[n].n = num;
  833.     if (++n == maxval) {
  834.       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
  835.       if (doub == NULL) {
  836.          farmemfree(ret);
  837.          ts->stackoflow = 1;
  838.          return NULL;
  839.          }
  840.       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
  841.       farmemfree(ret);
  842.       ret = doub;
  843.       maxval <<= 1;
  844.     }
  845.     s++;
  846.   }
  847.   ret[n].ch = 0;
  848.   ret[n].f = NULL;
  849.   ret[n].n = 0;
  850.   n++;
  851.  
  852.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  853.   if (doub == NULL) {
  854.        farmemfree(ret);
  855.        ts->stackoflow = 1;
  856.        return NULL;
  857.        }
  858.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  859.   farmemfree(ret);
  860.   return doub;
  861. }
  862.  
  863. static struct lsys_cmd far *
  864. LSysIDrawTransform(char far *s, struct lsys_turtlestatei *ts)
  865. {
  866.   struct lsys_cmd far *ret;
  867.   struct lsys_cmd far *doub;
  868.   int maxval = 10;
  869.   int n = 0;
  870.   void (*f)();
  871.   long num;
  872.  
  873.   void (*plus)() = (ispow2(ts->maxangle)) ? lsysi_doplus_pow2 : lsysi_doplus;
  874.   void (*minus)() = (ispow2(ts->maxangle)) ? lsysi_dominus_pow2 : lsysi_dominus;
  875.   void (*pipe)() = (ispow2(ts->maxangle)) ? lsysi_dopipe_pow2 : lsysi_dopipe;
  876.  
  877.   void (*slash)() =  (cpu >= 386) ? lsysi_doslash_386 : lsysi_doslash;
  878.   void (*bslash)() = (cpu >= 386) ? lsysi_dobslash_386 : lsysi_dobslash;
  879.   void (*at)() =     (cpu >= 386) ? lsysi_doat_386 : lsysi_doat;
  880.   void (*drawg)() =  (cpu >= 386) ? lsysi_dodrawg_386 : lsysi_dodrawg;
  881.  
  882.   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
  883.   if (ret == NULL) {
  884.        ts->stackoflow = 1;
  885.        return NULL;
  886.        }
  887.   while (*s) {
  888.     f = NULL;
  889.     num = 0;
  890.     ret[n].ch = *s;
  891.     switch (*s) {
  892.       case '+': f = plus;            break;
  893.       case '-': f = minus;           break;
  894.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  895.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  896.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  897.       case '|': f = pipe;            break;
  898.       case '!': f = lsysi_dobang;     break;
  899.       case 'd': f = lsysi_dodrawd;    break;
  900.       case 'm': f = lsysi_dodrawm;    break;
  901.       case 'g': f = drawg;           break;
  902.       case 'f': f = lsysi_dodrawf;    break;
  903.       case 'c': f = lsysi_dodrawc;    num = (long) getnumber(&s);    break;
  904.       case '<': f = lsysi_dodrawlt;   num = (long) getnumber(&s);    break;
  905.       case '>': f = lsysi_dodrawgt;   num = (long) getnumber(&s);    break;
  906.       case '[': num = 1;        break;
  907.       case ']': num = 2;        break;
  908.       default:
  909.     num = 3;
  910.     break;
  911.     }
  912. #ifdef XFRACT
  913.     ret[n].f = (void (*)())f;
  914. #else
  915.     ret[n].f = (void (*)(struct lsys_turtlestatei *))f;
  916. #endif
  917.     ret[n].n = num;
  918.     if (++n == maxval) {
  919.       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
  920.       if (doub == NULL) {
  921.            farmemfree(ret);
  922.            ts->stackoflow = 1;
  923.            return NULL;
  924.            }
  925.       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
  926.       farmemfree(ret);
  927.       ret = doub;
  928.       maxval <<= 1;
  929.     }
  930.     s++;
  931.   }
  932.   ret[n].ch = 0;
  933.   ret[n].f = NULL;
  934.   ret[n].n = 0;
  935.   n++;
  936.  
  937.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  938.   if (doub == NULL) {
  939.        farmemfree(ret);
  940.        ts->stackoflow = 1;
  941.        return NULL;
  942.        }
  943.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  944.   farmemfree(ret);
  945.   return doub;
  946. }
  947.  
  948. static void _fastcall lsysi_dosincos(void)
  949. {
  950.    double locaspect;
  951.    double TWOPI = 2.0 * PI;
  952.    double twopimax;
  953.    double twopimaxi;
  954.    double s, c;
  955.    int i;
  956.  
  957.    locaspect=screenaspect*xdots/ydots;
  958.    twopimax = TWOPI / maxangle;
  959.    for(i=0;i<maxangle;i++) {
  960.       twopimaxi = i * twopimax;
  961.       FPUsincos(&twopimaxi, &s, &c);
  962.       sins[i] = (long) (s * FIXEDLT1);
  963.       coss[i] = (long) ((locaspect * c) * FIXEDLT1);
  964.    }
  965. }
  966.